/*--------------------------------------------------------
Copyright (c) 2010 Apolo Pena

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------*/
package org.flashalchemy.ezlib.ezlog.console
{
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.GlowFilter;
    import mx.containers.Panel;
    import mx.core.SpriteAsset;
    import mx.core.UIComponent;
    import mx.events.FlexEvent;


    /**
     * <b>Description:</b> A draggable, resizeable Custom Panel Component.<p/>
     * <b>Usage:</b></br>
     * <pre>
     *      var draggablePanel:DragPanel = new DragPanel();
     * 		   addChild(draggablePanel);
     * </pre>
     */
    public class DraggableResizablePanel extends Panel
    {
        /**
         * Event name for when the user attempts to resize the Panel
         */
        public static const RESIZE_CLICK:String = "resizeClick";
        /**
         * Constructor calls super() and listens for a <code>FlexEvent.CREATION_COMPLETE</code> event.
         */
        public function DraggableResizablePanel()
        {
            super();
            addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
        }

        // Expose the title bar property for dragging and dropping.
        [Bindable]
        /**
         * The title bar component within the Panel
         */
        public var myTitleBar:UIComponent;

        private function creationCompleteHandler(event:Event):void
        {
            myTitleBar = titleBar;
            addEventListener(MouseEvent.MOUSE_DOWN, onResize);
        }
        /**
         * Override, see code
         */
        override protected function createChildren():void
        {
            super.createChildren();
            if (!minimizeIcon)
            {
                minimizeIcon = new SpriteAsset();
            }
            if (!restoreIcon)
            {
                restoreIcon = new SpriteAsset();
            }
            if (!resizeIcon)
            {
                resizeIcon = new UIComponent();
            }
            minimizeIcon.addEventListener(MouseEvent.MOUSE_DOWN, minPanelSizeHandler);
            minimizeIcon.addEventListener(MouseEvent.MOUSE_OVER, onMinShapeRollOver);
            minimizeIcon.addEventListener(MouseEvent.MOUSE_OUT, onMinShapeRollOut);
            titleBar.addChild(minimizeIcon);
            restoreIcon.addEventListener(MouseEvent.MOUSE_DOWN, restorePanelSizeHandler);
            restoreIcon.addEventListener(MouseEvent.MOUSE_OVER, onRestoreShapeRollOver);
            restoreIcon.addEventListener(MouseEvent.MOUSE_OUT, onRestoreShapeRollOut);
            titleBar.addChild(restoreIcon);
            titleBar.addChildAt(resizeIcon, titleBar.numChildren - 1);
        }
        /**
         * Event handler for when the minimize icon is rolled over by the user
         */
        protected function onMinShapeRollOver(me:MouseEvent):void
        {
            minimizeIcon.filters = [ new GlowFilter(0x55DFFF, 1, 9, 9, 1.5)];
        }
        /**
         * Event handler for when the minimize icon is rolled out by the user
         */
        protected function onMinShapeRollOut(me:MouseEvent):void
        {
            minimizeIcon.filters = [];
        }
        /**
         * Event handler for when the restore icon is rolled over by the user
         */
        protected function onRestoreShapeRollOver(me:MouseEvent):void
        {
            restoreIcon.filters = [ new GlowFilter(0x55DFFF, 1, 12, 12, 1)];
        }
        /**
         * Event handler for when the restor icon is rolled out by the user
         */
        protected function onRestoreShapeRollOut(me:MouseEvent):void
        {
            restoreIcon.filters = [];
        }
        /**
         * Override, see code
         */
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
            createTitleBarUi(unscaledWidth, unscaledHeight);
        }

        /**
         *  Shape representing the minimized icon in the panl,  drawn with the drawing API.
         */
        protected var minimizeIcon:SpriteAsset;

        /**
         *  Shape representing the restore icon in the panl,  drawn with the drawing API.
         */
        protected var restoreIcon:SpriteAsset;

        /**
         *  Shape representing the resize icon in the panl,  drawn with the drawing API.
         */
        protected var resizeIcon:UIComponent;

        /**
         * Creates the User Interface for the title bar of this component
         */
        protected function createTitleBarUi(unscaledWidth:Number, unscaledHeight:Number, iconColor:Number = 0):void
        {
            // Create invisible rectangle to increase the hit area of the min icon.
            if (!minimizeIcon)
            {
                minimizeIcon = new SpriteAsset();
            }
            if (!restoreIcon)
            {
                restoreIcon = new SpriteAsset();
            }
            if (!resizeIcon)
            {
                resizeIcon = new UIComponent(); // custom borderskins dont seem to want a child of SpriteAsset for some reason
            }
            minimizeIcon.graphics.clear();
            minimizeIcon.graphics.lineStyle(0, 0, 0);
            minimizeIcon.graphics.beginFill(0xFFFFFF, 0.0);
            minimizeIcon.graphics.drawRect(unscaledWidth - 35, 40, 8, 8);
            // Draw min icon.
            minimizeIcon.graphics.lineStyle(2, iconColor);
            minimizeIcon.graphics.beginFill(0xFFFFFF, 0.0);
            minimizeIcon.graphics.drawRect(unscaledWidth - 35, 18, 8, 2);
            // Draw restore icon.
            restoreIcon.graphics.clear();
            restoreIcon.graphics.lineStyle(2, iconColor);
            restoreIcon.graphics.beginFill(0xFFFFFF, 0.0);
            restoreIcon.graphics.drawRect(unscaledWidth - 20, 12, 8, 8);
            restoreIcon.graphics.moveTo(unscaledWidth - 20, 15);
            restoreIcon.graphics.lineTo(unscaledWidth - 12, 15);
            // Draw resize graphics if not minimized.				
            if (isMinimized == false)
            {
                resizeIcon.graphics.clear();
                resizeIcon.graphics.lineStyle(.25, iconColor);
                resizeIcon.graphics.moveTo(unscaledWidth - 6, unscaledHeight - 1)
                resizeIcon.graphics.curveTo(unscaledWidth - 3, unscaledHeight - 3, unscaledWidth - 1, unscaledHeight - 6);
                resizeIcon.graphics.moveTo(unscaledWidth - 6, unscaledHeight - 4)
                resizeIcon.graphics.curveTo(unscaledWidth - 5, unscaledHeight - 5, unscaledWidth - 4, unscaledHeight - 6);
            }
            else
            {
                resizeIcon.visible = false;
            }
        }

        private var myRestoreHeight:int;

        /**
         * Internal flag that tracks if the panel is minimized or not
         **/
        protected var isMinimized:Boolean = false;

        // Minimize panel event handler.
        private function minPanelSizeHandler(event:Event):void
        {
            if (isMinimized != true)
            {
                dispatchEvent(new Event(Event.CLOSE));
                myRestoreHeight = height;
                height = titleBar.height;
                isMinimized = true;
                // Don't allow resizing when in the minimized state.
                removeEventListener(MouseEvent.MOUSE_DOWN, onResize);
            }
        }

        private function restorePanelSizeHandler(event:Event):void
        {
            if (isMinimized == true)
            {
                dispatchEvent(new Event(Event.OPEN));
                height = myRestoreHeight;
                resizeIcon.visible = true;
                isMinimized = false;
                // Allow resizing in restored state.				
                addEventListener(MouseEvent.MOUSE_DOWN, onResize);
            }
        }

        /**
         * Event handler for when the user attempts to resize the Panel
         * @param event
         */
        protected function onResize(event:MouseEvent):void
        {
            // Determine if the mouse pointer is in the lower right 7x7 pixel
            // area of the panel. Initiate the resize if so.
            // Lower left corner of panel
            var lowerLeftX:Number = x + width;
            var lowerLeftY:Number = y + height;
            // Upper left corner of 7x7 hit area
            var upperLeftX:Number = lowerLeftX - 7;
            var upperLeftY:Number = lowerLeftY - 7;
            // Mouse positionin Canvas
            var panelRelX:Number = event.localX + x;
            var panelRelY:Number = event.localY + y;
            // Determine if the mousedown is in the lower right 7x7 pixel area
            // of the panel.
            if (upperLeftX <= panelRelX && panelRelX <= lowerLeftX)
            {
                if (upperLeftY <= panelRelY && panelRelY <= lowerLeftY)
                {
                    event.stopPropagation();
                    var rbEvent:MouseEvent = new MouseEvent(RESIZE_CLICK, true);
                    // Pass stage coords to so all calculations using global coordinates.
                    rbEvent.localX = event.stageX;
                    rbEvent.localY = event.stageY;
                    dispatchEvent(rbEvent);
                }
            }
        }
    }
}

